package cn.com.vs.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.log4j.Logger;

import cn.com.vs.Configurator;
import cn.com.vs.service.domain.ActivityBrief;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.http.UrlEncodedContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.JsonObjectParser;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.GenericData;

public class CloudMapService {
	private static Logger logger = Logger.getLogger(CloudMapService.class);
	private static CloudMapService instance = null;
	private static String cloudApiUrl_dataCreate = "http://yuntuapi.amap.com/datamanage/data/create";
	private static String cloudApiUrl_dataUpdate = "http://yuntuapi.amap.com/datamanage/data/update";
	private static String cloudApiUrl_dataDelete = "http://yuntuapi.amap.com/datamanage/data/delete";
	private static String cloudApiUrl_dataQuery = "http://yuntuapi.amap.com/datasearch/id";
	private static String cloudApiUrl_localSearch = "http://yuntuapi.amap.com/datasearch/local";
	private static String cloudApiUrl_aroundSearch = "http://yuntuapi.amap.com/datasearch/around";
	private static String cloudApiUrl_polygonSearch = "http://yuntuapi.amap.com/datasearch/polygon";
	//逆向的地址解析
	//http://restapi.amap.com/v3/geocode/regeo?key=3acb0053509adbf2e08f23307b5bbcec&location=121.47,31.22
	HttpRequestFactory requestFactory = null;
	JsonFactory JSON_FACTORY = null;
	private String key;
	private String activity_tableid;
	private String user_tableid;
	public static void init(){
		instance = new CloudMapService();
	}
	private CloudMapService(){
		JSON_FACTORY = new JacksonFactory();
		requestFactory = new NetHttpTransport().createRequestFactory(new HttpRequestInitializer() {
					@Override
					public void initialize(HttpRequest request) {
						request.setParser(new JsonObjectParser(JSON_FACTORY));
					}
				});
		key = Configurator.getInstance().getString("yuntu_appkey");
		activity_tableid = Configurator.getInstance().getString("yuntu_activity_tableid");
		user_tableid = Configurator.getInstance().getString("yuntu_user_tableid");
	};
	public static CloudMapService getInstance(){
		return instance;
	}
	
	public int createAnnotation(String name,String address,String longitude,String latitude,int type,int activityid,String digest, Integer openTime, Integer closeTime)
	{
		return createAnnotation(name, address, longitude+","+latitude, type, activityid,digest, openTime, closeTime);
	}
	
	public int createAnnotation(String name,String address,String location,int type,int activityid,String digest, Integer openTime, Integer closeTime)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_dataCreate );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",activity_tableid );
			JSONObject annotationData = new JSONObject();
			annotationData.put("_name", name);
			annotationData.put("_location", location );
			annotationData.put("_address", address );
			annotationData.put("type", type);
			annotationData.put("activity", activityid);
			annotationData.put("digest", digest);
			annotationData.put("openTime", openTime);
			annotationData.put("closeTime", closeTime);
			data.put("data", annotationData.toJSONString());
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					return obj.getIntValue("_id");
				}else{
					logger.error("createAnnotation faild,info:"+obj.getString("info"));
				}
				return -1;
			}else{
				logger.error("createAnnotation faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("createAnnotation exception:",e);
		}
		return -1;
	}
	
	
	public boolean updateAnnotation(int id,String name,String location,String type, Integer openTime, Integer closeTime)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_dataUpdate );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",activity_tableid );
			JSONObject annotationData = new JSONObject();
			if( name != null )
				annotationData.put("_name", name);
			if( location != null )
				annotationData.put("_location", location );
			if( type != null )
				annotationData.put("type", type);			
			annotationData.put("_id", id);
			if( openTime != null )
				annotationData.put("openTime", openTime);
			if( closeTime != null)
				annotationData.put("closeTime", closeTime);
			data.put("data", annotationData.toJSONString());
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					return true;
				}else{
					logger.error("updateAnnotation faild,info:"+obj.getString("info"));
				}
				return false;
			}else{
				logger.error("updateAnnotation faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("updateAnnotation exception:",e);
		}
		return false;
	}
	
	public boolean deleteAnnotation(int id)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_dataDelete );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",activity_tableid );
			data.put("ids", id);
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				return s!=null&&s==1;
			}else{
				logger.error("deleteAnnotation faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("deleteAnnotation exception:",e);
		}
		return false;
	}
	
	public List<ActivityBrief> getLocalAnnotationBrief(String keywords,String city,Integer type)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_localSearch );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",activity_tableid );
			data.put("keywords", StringUtils.isBlank(keywords)?" ":keywords);
			data.put("city", city);
			data.put("limit", 100);
			if( type!= null ){
				data.put("filter", "type:"+type+"+closeTime:["+ new Date().getTime()/1000 +",99999999999"+"]");
			}
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					JSONArray datas = obj.getJSONArray("datas");
					if( datas.isEmpty() )
						return Collections.emptyList();
					List<ActivityBrief> result = new ArrayList<ActivityBrief>();
					for(Object each : datas )
					{
						JSONObject act = (JSONObject)each;
						ActivityBrief brief = new ActivityBrief();
						brief.setId( act.getIntValue("activity"));
						brief.setDigest( act.getString("digest") );
						brief.setType( act.getIntValue("type") );
						brief.setName( act.getString("_name"));
						brief.setCoord( act.getString("_location") );
						result.add(brief);
					}
					return result;
				}else{
					logger.error("getLocalAnnotationBrief faild,info:"+obj.getString("info"));
				}
				return null;
			}else{
				logger.error("getLocalAnnotationBrief faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getLocalAnnotationBrief exception:",e);
		}
		return null;
	}
	

	public List<ActivityBrief> getAroundAnnotationBrief(String center,int radius,String keywords,Integer type)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_aroundSearch );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",activity_tableid );
			data.put("center", center);
			data.put("radius", radius);
			if( !StringUtils.isBlank( keywords ) ){
				data.put("keywords", keywords);
			}
			if( type != null ){
				data.put("filter", "type:"+type+"+closeTime:["+ new Date().getTime()/1000 +",99999999999"+"]");
			}
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					JSONArray datas = obj.getJSONArray("datas");
					if( datas.isEmpty() )
						return Collections.emptyList();
					List<ActivityBrief> result = new ArrayList<ActivityBrief>();
					for(Object each : datas )
					{
						JSONObject act = (JSONObject)each;
						ActivityBrief brief = new ActivityBrief();
						brief.setId( act.getIntValue("activity"));
						brief.setDigest( act.getString("digest") );
						brief.setType( act.getIntValue("type") );
						brief.setName( act.getString("_name"));
						brief.setCoord( act.getString("_location") );
						brief.setDistance( act.getIntValue("_distance"));
						result.add(brief);
					}
					return result;
				}else{
					logger.error("getLocalAnnotationBrief faild,info:"+obj.getString("info"));
				}
				return null;
			}else{
				logger.error("getLocalAnnotationBrief faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getLocalAnnotationBrief exception:",e);
		}
		return null;
	}
	
	public List<ActivityBrief> getRegionAnnotationBrief(String keywords,String region,Integer type)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_polygonSearch );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",activity_tableid );
			data.put("keywords", StringUtils.isBlank(keywords)?"":keywords);
			data.put("polygon", region);
			data.put("limit", 100);
			if( type!= null ){
				data.put("filter", "type:"+type+"+closeTime:["+ new Date().getTime()/1000 +",99999999999"+"]");
			}
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					JSONArray datas = obj.getJSONArray("datas");
					if( datas.isEmpty() )
						return Collections.emptyList();
					List<ActivityBrief> result = new ArrayList<ActivityBrief>();
					for(Object each : datas )
					{
						JSONObject act = (JSONObject)each;
						ActivityBrief brief = new ActivityBrief();
						brief.setId( act.getIntValue("activity"));
						brief.setDigest( act.getString("digest") );
						brief.setType( act.getIntValue("type") );
						brief.setName( act.getString("_name"));
						brief.setCoord( act.getString("_location") );
						result.add(brief);
					}
					return result;
				}else{
					logger.error("getRegionAnnotationBrief faild region="+region+",insfo:"+obj.getString("info"));
				}
				return null;
			}else{
				logger.error("getRegionAnnotationBrief faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getRegionAnnotationBrief exception:",e);
		}
		return null;
	}
	
	public int createUserLocData(String name,String longitude,String latitude,int type,int userid)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_dataCreate );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",user_tableid );
			JSONObject annotationData = new JSONObject();
			annotationData.put("_name", name);
			annotationData.put("_location", longitude+","+latitude );
			annotationData.put("type", type);
			annotationData.put("userid", userid);
			data.put("data", annotationData.toJSONString());
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					return obj.getIntValue("_id");
				}else{
					logger.error("createUserLocData faild,info:"+obj.getString("info"));
				}
				return -1;
			}else{
				logger.error("createUserLocData faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("createUserLocData exception:",e);
		}
		return -1;
	}
	
	public Map<Integer,String> getLocalUsers(String city,Integer type)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_localSearch );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",user_tableid );
			data.put("keywords", " ");
			data.put("city", city);
			data.put("limit", 100);
			if( type!= null ){
				data.put("filter", "type:"+type);
			}
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					JSONArray datas = obj.getJSONArray("datas");
					if( datas.isEmpty() )
						return Collections.emptyMap();
					Map<Integer,String> result = new HashMap<Integer,String>();
					for(Object each : datas )
					{
						JSONObject act = (JSONObject)each;
						result.put(act.getInteger("userid"), act.getString("_location"));
					}
					return result;
				}else{
					logger.error("getLocalAnnotationBrief faild,info:"+obj.getString("info"));
				}
				return null;
			}else{
				logger.error("getLocalAnnotationBrief faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getLocalAnnotationBrief exception:",e);
		}
		return null;
	}
	
	public boolean updateUserLocData(int id,String name,String longitude,String latitude)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_dataUpdate );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",user_tableid );
			JSONObject annotationData = new JSONObject();
			if( name != null )
				annotationData.put("_name", name);
			annotationData.put("_location", longitude+","+latitude );
			annotationData.put("_id", id);
			data.put("data", annotationData.toJSONString());
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				if( s!=null&&s==1 ){
					return true;
				}else{
					logger.error("updateUserLocData faild,info:"+obj.getString("info"));
				}
				return false;
			}else{
				logger.error("updateUserLocData faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("updateUserLocData exception:",e);
		}
		return false;
	}
	
	public boolean deleteUserLoc(int id)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_dataDelete );
			GenericData data = new GenericData();
			data.put("key",key );
			data.put("tableid",user_tableid );
			data.put("ids", id);
			UrlEncodedContent content = new UrlEncodedContent(data);
			HttpRequest request = requestFactory.buildPostRequest(url, content);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				Integer s = obj.getInteger("status");
				return s!=null&&s==1;
			}else{
				logger.error("deleteUserLoc faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("deleteUserLoc exception:",e);
		}
		return false;
	}
	
	public JSONObject getUserLocation(int locid)
	{
		try{
			GenericUrl  url = new GenericUrl( cloudApiUrl_dataQuery );
			url.put("key",key );
			url.put("tableid",user_tableid );
			url.put("_id", locid);
			HttpRequest request = requestFactory.buildGetRequest(url);
			HttpResponse resp = request.execute();
			int statusCode = resp.getStatusCode();	
			if( statusCode == HttpStatus.SC_OK ){
				JSONObject obj = JSONObject.parseObject(resp.parseAsString());
				return obj;
			}else{
				logger.error("getUserLocation faild:status="+statusCode+" msg="+resp.getStatusMessage());
			}
		}catch(Exception e){
			logger.error("getUserLocation exception:",e);
		}
		return null;
	}
	
}
